home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / text / misc / tr.lha / Tr / src / tr.c < prev   
C/C++ Source or Header  |  1995-01-08  |  8KB  |  290 lines

  1. /*
  2.  * Copyright (c) 1988, 1993
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char copyright[] =
  36. "@(#) Copyright (c) 1988, 1993\n\
  37.     The Regents of the University of California.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)tr.c    8.1 (Berkeley) 6/6/93";
  42. #endif /* not lint */
  43.  
  44. #ifndef AZTEC_C
  45. #include <types.h>
  46. #endif
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #include "extern.h"
  51.  
  52. static int string1[NCHARS] = {
  53.     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,        /* ASCII */
  54.     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  55.     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  56.     0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  57.     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
  58.     0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  59.     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
  60.     0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  61.     0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
  62.     0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
  63.     0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
  64.     0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
  65.     0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
  66.     0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
  67.     0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
  68.     0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
  69.     0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
  70.     0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
  71.     0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
  72.     0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
  73.     0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
  74.     0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
  75.     0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
  76.     0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
  77.     0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
  78.     0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
  79.     0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
  80.     0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
  81.     0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
  82.     0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
  83.     0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
  84.     0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
  85. }, string2[NCHARS];
  86.  
  87. STR s1 = { STRING1, NORMAL, 0, OOBCH, { 0, OOBCH }, NULL, NULL };
  88. STR s2 = { STRING2, NORMAL, 0, OOBCH, { 0, OOBCH }, NULL, NULL };
  89.  
  90. static void setup (int *, char *, STR *, int);
  91. static void usage (void);
  92.  
  93. int
  94. main(argc, argv)
  95.     int argc;
  96.     char **argv;
  97. {
  98.     register int ch, cnt, lastch, *p;
  99.     int cflag, dflag, sflag, isstring2;
  100.  
  101.     cflag = dflag = sflag = 0;
  102.     while ((ch = getopt(argc, argv, "cds")) != EOF)
  103.         switch((char)ch) {
  104.         case 'c':
  105.             cflag = 1;
  106.             break;
  107.         case 'd':
  108.             dflag = 1;
  109.             break;
  110.         case 's':
  111.             sflag = 1;
  112.             break;
  113.         case '?':
  114.         default:
  115.             usage();
  116.         }
  117.     argc -= optind;
  118.     argv += optind;
  119.  
  120.     switch(argc) {
  121.     case 0:
  122.     default:
  123.         usage();
  124.         /* NOTREACHED */
  125.     case 1:
  126.         isstring2 = 0;
  127.         break;
  128.     case 2:
  129.         isstring2 = 1;
  130.         break;
  131.     }
  132.  
  133.     /*
  134.      * tr -ds [-c] string1 string2
  135.      * Delete all characters (or complemented characters) in string1.
  136.      * Squeeze all characters in string2.
  137.      */
  138.     if (dflag && sflag) {
  139.         if (!isstring2)
  140.             usage();
  141.  
  142.         setup(string1, argv[0], &s1, cflag);
  143.         setup(string2, argv[1], &s2, 0);
  144.         
  145.         for (lastch = OOBCH; (ch = getchar()) != EOF;)
  146.             if (!string1[ch] && (!string2[ch] || lastch != ch)) {
  147.                 lastch = ch;
  148.                 (void)putchar(ch);
  149.             }
  150.         exit(0);
  151.     }
  152.  
  153.     /*
  154.      * tr -d [-c] string1
  155.      * Delete all characters (or complemented characters) in string1.
  156.      */
  157.     if (dflag) {
  158.         if (isstring2)
  159.             usage();
  160.  
  161.         setup(string1, argv[0], &s1, cflag);
  162.  
  163.         while ((ch = getchar()) != EOF)
  164.             if (!string1[ch])
  165.                 (void)putchar(ch);
  166.         exit(0);
  167.     }
  168.  
  169.     /*
  170.      * tr -s [-c] string1
  171.      * Squeeze all characters (or complemented characters) in string1.
  172.      */
  173.     if (sflag && !isstring2) {
  174.         setup(string1, argv[0], &s1, cflag);
  175.  
  176.         for (lastch = OOBCH; (ch = getchar()) != EOF;)
  177.             if (!string1[ch] || lastch != ch) {
  178.                 lastch = ch;
  179.                 (void)putchar(ch);
  180.             }
  181.         exit(0);
  182.     }
  183.  
  184.     /*
  185.      * tr [-cs] string1 string2
  186.      * Replace all characters (or complemented characters) in string1 with
  187.      * the character in the same position in string2.  If the -s option is
  188.      * specified, squeeze all the characters in string2.
  189.      */
  190.     if (!isstring2)
  191.         usage();
  192.  
  193.     s1.str = argv[0];
  194.     s2.str = argv[1];
  195.  
  196.     if (cflag)
  197.         for (cnt = NCHARS, p = string1; cnt--;)
  198.             *p++ = OOBCH;
  199.  
  200.     if (!next(&s2))
  201.         err("empty string2");
  202.  
  203.     /* If string2 runs out of characters, use the last one specified. */
  204.     if (sflag)
  205.         while (next(&s1)) {
  206.             string1[s1.lastch] = ch = s2.lastch;
  207.             string2[ch] = 1;
  208.             (void)next(&s2);
  209.         }
  210.     else
  211.         while (next(&s1)) {
  212.             string1[s1.lastch] = ch = s2.lastch;
  213.             (void)next(&s2);
  214.         }
  215.  
  216.     if (cflag)
  217.         for (cnt = 0, p = string1; cnt < NCHARS; ++p, ++cnt)
  218.             *p = *p == OOBCH ? ch : cnt;
  219.  
  220.     if (sflag)
  221.         for (lastch = OOBCH; (ch = getchar()) != EOF;) {
  222.             ch = string1[ch];
  223.             if (!string2[ch] || lastch != ch) {
  224.                 lastch = ch;
  225.                 (void)putchar(ch);
  226.             }
  227.         }
  228.     else
  229.         while ((ch = getchar()) != EOF)
  230.             (void)putchar(string1[ch]);
  231.     exit (0);
  232. }
  233.  
  234. static void
  235. setup(string, arg, str, cflag)
  236.     int *string;
  237.     char *arg;
  238.     STR *str;
  239.     int cflag;
  240. {
  241.     register int cnt, *p;
  242.  
  243.     str->str = arg;
  244.     bzero(string, NCHARS * sizeof(int));
  245.     while (next(str))
  246.         string[str->lastch] = 1;
  247.     if (cflag)
  248.         for (p = string, cnt = NCHARS; cnt--; ++p)
  249.             *p = !*p;
  250. }
  251.  
  252. static void
  253. usage()
  254. {
  255.     (void)fprintf(stderr, "usage: tr [-cs] string1 string2\n");
  256.     (void)fprintf(stderr, "       tr [-c] -d string1\n");
  257.     (void)fprintf(stderr, "       tr [-c] -s string1\n");
  258.     (void)fprintf(stderr, "       tr [-c] -ds string1 string2\n");
  259.     exit(1);
  260. }
  261.  
  262. #ifdef  __STDC__
  263. #include <stdarg.h>
  264. #else
  265. #include <varargs.h>
  266. #endif
  267.  
  268. void
  269. #ifdef __STDC__
  270. err(const char *fmt, ...)
  271. #else
  272. err(fmt, va_alist)
  273.     char *fmt;
  274.         va_dcl
  275. #endif
  276. {
  277.     va_list ap;
  278. #ifdef  __STDC__
  279.     va_start(ap, fmt);
  280. #else
  281.     va_start(ap);
  282. #endif
  283.     (void)fprintf(stderr, "tr: ");
  284.     (void)vfprintf(stderr, fmt, ap);
  285.     va_end(ap);
  286.     (void)fprintf(stderr, "\n");
  287.     exit(1);
  288.     /* NOTREACHED */
  289. }
  290.